package com.dge.common.base.view

import android.app.Activity
import android.content.Context
import android.content.Intent
import android.graphics.drawable.ColorDrawable
import android.os.Bundle
import android.util.SparseArray
import android.view.KeyEvent
import android.view.View
import android.view.ViewGroup
import android.view.Window
import androidx.annotation.StringRes
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.lifecycle.Lifecycle
import androidx.viewbinding.ViewBinding
import com.dge.common.R
import com.dge.common.action.ActivityAction
import com.dge.common.action.KeyboardAction
import com.dge.common.action.TitleBarAction
import com.dge.common.action.ToastAction
import com.dge.common.common.AppConfig
import com.dge.common.extentions.hideNavigationBar
import com.dge.common.utils.LoadingDialogUtils
import com.dge.common.utils.OkHttpUtils
import com.dylanc.viewbinding.base.ActivityBinding
import com.dylanc.viewbinding.base.ActivityBindingDelegate
import com.hjq.bar.TitleBar
import com.lxj.xpopup.impl.LoadingPopupView
import com.zackratos.ultimatebarx.ultimatebarx.navigationBar
import com.zackratos.ultimatebarx.ultimatebarx.statusBar
import kotlinx.coroutines.CoroutineScope
import org.greenrobot.eventbus.EventBus
import timber.log.Timber
import java.util.*
import kotlin.coroutines.CoroutineContext
import kotlin.math.pow

open class BaseActivity<T : ViewBinding> : AppCompatActivity(), MvpView,
    TitleBarAction, ActivityAction, KeyboardAction, ToastAction, CoroutineScope, ActivityBinding<T> by ActivityBindingDelegate() {
    var isSetStatusBarColor = true

    //协程
    override val coroutineContext: CoroutineContext
        get() = kotlinx.coroutines.Dispatchers.Main
    var savedInstanceState: Bundle? = null
    val isDebug: Boolean get() = AppConfig.isDebug()
    val loadingDialog: LoadingPopupView?
        get() = LoadingDialogUtils.dialogMap[localClassName]

    /** 标题栏对象  */
    private var titleBar: TitleBar? = null
    private var isReleaseCalledInPause = false

    /** Activity 回调集合 */
    private val activityCallbacks: SparseArray<OnActivityCallback?> by lazy { SparseArray(1) }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // TheRouter.inject(this)
        setContentViewWithBinding()
        setSystemBarColor()
        initSoftKeyboard()
        getTitleBar()?.setOnTitleBarListener(this)
    }

    //在setContentView后执行才会生效
    open fun setSystemBarColor(isfitWindow: Boolean = false, isLight: Boolean = false, colorResId: Int = R.color.transparent) {
        if (isFinished() || !isSetStatusBarColor) return
        //Utils.setImmersiveStatusOrNavBar(this, true, true, false)
        statusBar {
            fitWindow = isfitWindow
            light = isLight
            colorRes = colorResId
        }
        setNavigationBarStatus()
    }

    open fun setNavigationBarStatus(isImmersive: Boolean = false, colorRes: Int = -1) {
        // Timber.i("isNavBarVisible = ${BarUtils.isNavBarVisible(this)}")
        navigationBar {
            if (isImmersive) {
                transparent()
            } else {
                fitWindow = true
                light = !AppConfig.isDarkTheme()
                if (colorRes != -1) {
                    this.colorRes = colorRes
                } else {
                    val drawable = binding.root.background
                    if (drawable is ColorDrawable) {
                        this.color = drawable.color
                    }
                }
            }
        }
    }

    /**
     * 如果当前的 Activity（singleTop 启动模式） 被复用时会回调
     */
    override fun onNewIntent(intent: Intent?) {
        super.onNewIntent(intent)
        // 设置为当前的 Intent，避免 Activity 被杀死后重启 Intent 还是最原先的那个
        setIntent(intent)
    }

    fun showLoading(
        activity: Activity = this,
        msg: String? = null,
        dismissOnBackPressed: Boolean = true,
        dismissOnTouchOutside: Boolean = true,
        isLightStatusBar: Boolean = true
    ) {
        LoadingDialogUtils.showLoading(activity, msg, dismissOnBackPressed, dismissOnTouchOutside, isLightStatusBar)
    }

    override fun showLoading() {
        showLoading(this, null, true, true, true)
    }

    override fun showLoading(msg: String) {
        showLoading(this, msg, true, true, true)
    }

    override fun hideLoading() {
        if (isFinished()) return
        LoadingDialogUtils.hideLoading(this)
    }

    override fun onPause() {
        super.onPause()
        if (AppConfig.isDebug()) Timber.i("onPause isFinishing = $isFinishing, simpleName = ${javaClass.simpleName}")
        if (isFinishing) {
            /**
             * 如果activity实现了一个回调接口，然后使用 this 设置给需要回调接口的方法，最常见的就是实现 onClickListener 接口，然后 findViewById().setOnClickListenr(this)。
             * 如果，这个回调接口设置到了一个静态对象（单例模式），当 activity finish() 的时候（按返回键，回到桌面），则activity 不会被调用 onDestroy() ，原因可能是 activity 对象还在被引用！
             * 此时你再点击图标回到应用，onCreate() 再次调用！
             * 很明显，如果你把资源释放放在了 onDestroy() 里面，就会导致内存泄露！
             * 这时可以在 onPause() 方法里面判断 isFinishing() ，正常调用 finish() 后 activity 的回调过程是 onPause、onStop、onDestroy ，
             * 倘若出现上面的情况，只到 onPause！但是 isFinishing() 标志还是为 true ！你可以释放资源了。
             */
            isReleaseCalledInPause = true
            release()
        }
    }

    /**
     * 释放资源，其它的的一些方法可以往里添加
     */
    open fun release() {
        if (AppConfig.isDebug()) Timber.i("release called, simpleName = ${javaClass.simpleName}")
        //取消HttpUtils方式的请求
        OkHttpUtils.cancelTag(this)
    }

    override fun onDestroy() {
        if (AppConfig.isDebug()) Timber.i("onDestroy, isFinishing = $isFinishing, isDestroyed = $isDestroyed, simpleName = ${javaClass.simpleName}")
        if (!isReleaseCalledInPause) {
            release()
        }
        super.onDestroy()
    }

    override fun onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)
        savedInstanceState = null
        //outState.putSerializable("user", CommandController.user)
    }

    override fun onRestoreInstanceState(savedInstanceState: Bundle) {
        super.onRestoreInstanceState(savedInstanceState)
        this.savedInstanceState = savedInstanceState
    }

    /**
     * 初始化软键盘
     */
    protected open fun initSoftKeyboard() {
        // 点击外部隐藏软键盘，提升用户体验
        getContentView()?.setOnClickListener {
            // 隐藏软键，避免内存泄漏
            hideKeyboard(currentFocus)
        }
    }

    fun getContentView(): ViewGroup? {
        return findViewById(Window.ID_ANDROID_CONTENT)
    }

    fun isFinished(): Boolean {
        return isFinishing || isDestroyed
    }

    override fun getTitleBar(): TitleBar? {
        if (titleBar == null) {
            titleBar = obtainTitleBar(getContentView())
        }
        return titleBar
    }

    /**
     * 设置标题栏的标题
     */
    override fun setTitle(@StringRes id: Int) {
        title = getString(id)
    }

    /**
     * 设置标题栏的标题
     */
    override fun setTitle(title: CharSequence?) {
        if (getTitleBar() != null) {
            titleBar!!.title = title
        }
    }

    override fun onLeftClick(titleBar: TitleBar) {
        onBackPressed()
    }

    override fun getContext(): Context {
        return this
    }

    override fun startActivity(intent: Intent) {
        return super<AppCompatActivity>.startActivity(intent)
    }

    override fun dispatchKeyEvent(event: KeyEvent?): Boolean {
        val fragments: MutableList<Fragment?> = supportFragmentManager.fragments
        for (fragment: Fragment? in fragments) {
            // 这个 Fragment 必须是 BaseFragment 的子类，并且处于可见状态
            if (fragment !is BaseFragment<*> || fragment.lifecycle.currentState != Lifecycle.State.RESUMED) {
                continue
            }
            // 将按键事件派发给 Fragment 进行处理
            if (fragment.dispatchKeyEvent(event)) {
                // 如果 Fragment 拦截了这个事件，那么就不交给 Activity 处理
                return true
            }
        }
        return super.dispatchKeyEvent(event)
    }

    @Deprecated("Deprecated in Java")
    override fun startActivityForResult(intent: Intent, requestCode: Int, options: Bundle?) {
        // 隐藏软键，避免内存泄漏
        hideKeyboard(currentFocus)
        // 查看源码得知 startActivity 最终也会调用 startActivityForResult
        super.startActivityForResult(intent, requestCode, options)
    }

    /**
     * startActivityForResult 方法优化
     */
    open fun startActivityForResult(clazz: Class<out Activity>, callback: OnActivityCallback?) {
        startActivityForResult(Intent(this, clazz), null, callback)
    }

    open fun startActivityForResult(intent: Intent, callback: OnActivityCallback?) {
        startActivityForResult(intent, null, callback)
    }

    @Suppress("deprecation")
    open fun startActivityForResult(intent: Intent, options: Bundle?, callback: OnActivityCallback?) {
        // 请求码必须在 2 的 16 次方以内
        val requestCode: Int = Random().nextInt(2.0.pow(16.0).toInt())
        activityCallbacks.put(requestCode, callback)
        startActivityForResult(intent, requestCode, options)
    }

    @Deprecated("Deprecated in Java")
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        var callback: OnActivityCallback?
        if ((activityCallbacks.get(requestCode).also { callback = it }) != null) {
            callback?.onActivityResult(resultCode, data)
            activityCallbacks.remove(requestCode)
            return
        }
        super.onActivityResult(requestCode, resultCode, data)
    }

    open fun hideSoftKeyboard() {
        hideKeyboard(currentFocus)
    }

    fun registerEventBus() {
        if (!EventBus.getDefault().isRegistered(this)) {
            EventBus.getDefault().register(this)
        }
    }

    fun unregisterEventBus() {
        if (EventBus.getDefault().isRegistered(this)) {
            EventBus.getDefault().unregister(this)
        }
    }

    interface OnActivityCallback {
        /**
         * 结果回调
         *
         * @param resultCode        结果码
         * @param data              数据
         */
        fun onActivityResult(resultCode: Int, data: Intent?)
    }

    fun hideNavigationBar() {
        val flags = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                or View.SYSTEM_UI_FLAG_FULLSCREEN
                or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY)
        if (window.decorView.systemUiVisibility != flags) {
            this.window.hideNavigationBar()
        }
    }
}